home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- NETBOOT - BOOTP/TFTP Bootstrap Program
-
- Author: Martin Renters
- Date: Dec/93
-
- **************************************************************************/
-
- /* #define MDEBUG */
-
- #include "netboot.h"
-
- int jmp_bootmenu[10];
-
- struct exec head;
- char *loadpoint;
- char *kernel;
- char kernel_buf[128];
- void (*kernelentry)();
- struct nfs_diskless nfsdiskless;
- int hostnamelen;
- char config_buffer[TFTP_MAX_PACKET+1]; /* +1 for null byte */
- struct bootinfo bootinfo;
- unsigned long netmask;
-
- char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-
- /**************************************************************************
- MAIN - Kick off routine
- **************************************************************************/
- #ifdef __linux
- extern int main P((void));
- int _main() {return main();}
- #endif
-
- int main()
- {
- extern char *linux_add_cmdline();
- char *p;
- for (p=_edata; p<_end; p++) *p = 0; /* Zero BSS */
- #ifdef ASK_BOOT
- while (1) {
- int c;
- printf("\n\rBoot from Network (Y/N) ? ");
- c = getchar();
- if ((c >= 'a') && (c <= 'z')) c &= 0x5F;
- if (c == '\r') break;
- putchar(c);
- if (c == 'N')
- exit(0);
- if (c == 'Y')
- break;
- printf(" - bad response\n\r");
- }
- #endif
- gateA20();
- #ifdef NETBOOT32
- printf("\r\nBOOTP/TFTP/NFS bootstrap loader " VERSION " ESC for menu\r\n\r\nSearching for adapter...");
- #endif
- #ifdef NETBOOT16
- /* bcc still doesn't do ANSI string concatenation so this is hardwired */
- printf("\r\nBOOTP/TFTP/NFS bootstrap loader 2.0 ESC for menu\r\n\r\nSearching for adapter...");
- #endif
- if (!eth_probe()) {
- printf("No adapter found.\r\n");
- exit(0);
- }
- kernel = DEFAULT_BOOTFILE;
- linux_add_cmdline(0); /* clear linux cmdline */
- while (1) {
- if (setjmp(jmp_bootmenu))
- bootmenu();
- else
- load();
- }
- }
-
- #ifdef NETBOOT32
- /**************************************************************************
- DOMOUNT - Try to mount FS
- **************************************************************************/
- void domount(char *s,int *port,int *mount_port,char *hostnam,char *fh,int arpserver,
- struct sockaddr_in *in_saddr,struct nfs_args *args,char *fnam,
- char *newfh)
- {
- int err;
- *port = rpclookup(arpserver, PROG_NFS, 2);
- *mount_port = rpclookup(arpserver, PROG_MOUNT, 1);
- if ((*port == -1) || (*mount_port == -1)) {
- printf("Unable to get %s NFS/MOUNT ports\r\n",s);
- bootmenu:
- longjmp(jmp_bootmenu,1); }
- if ((err = nfs_mount(arpserver, *mount_port, hostnam, fh))) {
- printf("Unable to mount %s filesystem: ",s);
- nfserr:
- nfs_err(err);
- goto bootmenu; }
- in_saddr->sin_len = sizeof(struct sockaddr_in);
- in_saddr->sin_family = AF_INET;
- in_saddr->sin_port = htons(*port);
- in_saddr->sin_addr.s_addr = htonl(arptable[arpserver].ipaddr);
- args->timeo = 10;
- args->retrans = 100;
- if ((err = nfs_lookup(arpserver,*port,fh,fnam,newfh))) {
- printf("Unable to open %s: ",fnam);
- goto nfserr; }
- return;
- }
- #endif /* NETBOOT32 */
-
- /**************************************************************************
- LOAD - Try to get booted
- **************************************************************************/
- void load()
- {
- char *p,*q;
- char cfg[64];
- int root_nfs_port;
- int root_mount_port;
- int swap_nfs_port;
- int swap_mount_port;
- char kernel_handle[32];
- char cmd_line[80];
- int err, offset, read_size;
- long addr, broadcast;
-
- /* Initialize this early on */
-
- nfsdiskless.root_args.rsize = 8192;
- nfsdiskless.root_args.wsize = 8192;
- nfsdiskless.swap_args.rsize = 8192;
- nfsdiskless.swap_args.wsize = 8192;
- nfsdiskless.root_args.sotype = SOCK_DGRAM;
- nfsdiskless.root_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE);
- nfsdiskless.swap_args.sotype = SOCK_DGRAM;
- nfsdiskless.swap_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE);
-
-
- /* Find a server to get BOOTP reply from */
- if (!arptable[ARP_CLIENT].ipaddr || !arptable[ARP_SERVER].ipaddr) {
- printf("\r\nSearching for server...\r\n");
- if (!bootp()) {
- printf("No Server found.\r\n");
- bootmenu:
- longjmp(jmp_bootmenu,1);
- }
- }
- printf("My IP %I, Server IP %I, GW IP %I\r\n",
- arptable[ARP_CLIENT].ipaddr,
- arptable[ARP_SERVER].ipaddr,
- arptable[ARP_GATEWAY].ipaddr);
-
- #ifdef MDEBUG
- printf("\n=>>"); getchar();
- #endif
-
- /* Now use TFTP to load configuration file */
- #if defined(PRIORIZEBOOTPKERNEL) && !defined(BOOTPKERNELONLY)
- printf(" \r\nLoading %s... ",kernel);
- if (!tftp(kernel)) {
- #endif
- #ifndef BOOTPKERNELONLY
- sprintf(cfg,"cfg.%I",arptable[ARP_CLIENT].ipaddr);
- printf(" \r\nLoading %s... ",cfg);
- if (!tftp(cfg)) {
- sprintf(cfg,"/tftpboot/cfg.%I",arptable[ARP_CLIENT].ipaddr);
- printf(" \r\nLoading %s... ",cfg);
- if (!tftp(cfg)) {
- #endif
- #ifndef PRIORIZEBOOTPKERNEL
- printf(" \r\nLoading %s... ",kernel);
- if (!tftp(kernel)) {
- #endif
- printf("Unable to load config file.\r\n");
- goto bootmenu;
- #if !defined(PRIORIZEBOOTPKERNEL) || \
- defined(PRIORIZEBOOTPKERNEL) && !defined(BOOTPKERNELONLY)
- }
- #endif
- #ifndef BOOTPKERNELONLY
- } }
- #endif
-
- #ifdef NETBOOT32
- #ifdef MDEBUG
- printf("\n=>>"); getchar();
- #endif
-
- p = config_buffer;
- while(*p) {
- q = cmd_line;
- while ((*p != '\n') && (*p)) *(q++) = *(p++);
- *q = 0;
- printf("%s\r\n",cmd_line);
- execute(cmd_line);
- if (*p) p++;
- }
-
- #ifdef MDEBUG
- printf("\n=>>"); getchar();
- #endif
-
- /* Check to make sure we've got a rootfs */
- if (!arptable[ARP_ROOTSERVER].ipaddr) {
- printf("No ROOT filesystem server!\r\n");
- goto bootmenu;
- }
-
- /* Fill in nfsdiskless.myif */
- sprintf(&nfsdiskless.myif.ifra_name,eth_driver);
- nfsdiskless.myif.ifra_addr.sa_len = sizeof(struct sockaddr);
- nfsdiskless.myif.ifra_addr.sa_family = AF_INET;
- addr = htonl(arptable[ARP_CLIENT].ipaddr);
- bcopy(&addr, &nfsdiskless.myif.ifra_addr.sa_data[2], 4);
- broadcast = (addr & netmask) | ~netmask;
- nfsdiskless.myif.ifra_broadaddr.sa_len = sizeof(struct sockaddr);
- nfsdiskless.myif.ifra_broadaddr.sa_family = AF_INET;
- bcopy(&broadcast, &nfsdiskless.myif.ifra_broadaddr.sa_data[2], 4);
- addr = htonl(arptable[ARP_GATEWAY].ipaddr);
- if (addr) {
- nfsdiskless.mygateway.sin_len = sizeof(struct sockaddr);
- nfsdiskless.mygateway.sin_family = AF_INET;
- bcopy(&addr, &nfsdiskless.mygateway.sin_addr, 4);
- } else {
- nfsdiskless.mygateway.sin_len = 0;
- }
- nfsdiskless.myif.ifra_mask.sa_len = sizeof(struct sockaddr);
- nfsdiskless.myif.ifra_mask.sa_family = AF_UNSPEC;
- bcopy(&netmask, &nfsdiskless.myif.ifra_mask.sa_data[2], 4);
-
- rpc_id = currticks();
-
- /* Lookup NFS/MOUNTD ports for SWAP using PORTMAP */
- if (arptable[ARP_SWAPSERVER].ipaddr) {
- char swapfs_fh[32], swapfile[32];
- sprintf(swapfile,"swap.%I",arptable[ARP_CLIENT].ipaddr);
- domount("SWAP",&swap_nfs_port,&swap_mount_port,nfsdiskless.swap_hostnam,
- swapfs_fh,ARP_SWAPSERVER,&nfsdiskless.swap_saddr,
- &nfsdiskless.swap_args,swapfile,nfsdiskless.swap_fh); }
-
- /* Lookup NFS/MOUNTD ports for ROOT using PORTMAP */
- domount("ROOT",&root_nfs_port,&root_mount_port,nfsdiskless.root_hostnam,
- nfsdiskless.root_fh,ARP_ROOTSERVER,&nfsdiskless.root_saddr,
- &nfsdiskless.root_args,*kernel == '/' ? kernel+1 : kernel,
- kernel_handle);
- nfsdiskless.root_time = 0;
-
- /* Load the kernel using NFS */
- printf("Loading %s...\r\n",kernel);
- if ((err = nfs_read(ARP_ROOTSERVER, root_nfs_port, (char *)&kernel_handle, 0,
- sizeof(struct exec), (char *)&head)) < 0) {
- printf("Unable to read %s: ",kernel);
- nfs_err(err);
- goto bootmenu;
- }
- if (N_BADMAG(head) &&
- !load_linux(root_mount_port,swap_mount_port,
- root_nfs_port,kernel_handle)) {
- printf("Bad executable format!\r\n");
- goto bootmenu;
- }
- loadpoint = (char *)0x100000;
- offset = N_TXTOFF(head);
- /* printf("text=0x%X, ",head.a_text); */
- while (head.a_text > 0) {
- read_size = head.a_text > NFS_READ_SIZE ?
- NFS_READ_SIZE : head.a_text;
- if ((err = nfs_read(ARP_ROOTSERVER, root_nfs_port,
- (char *)&kernel_handle, offset, read_size, loadpoint)) !=
- read_size) {
- if (err < 0) {
- /* printf("Unable to read text: "); */
- nfs_err(err);
- }
- goto bootmenu;
- }
- loadpoint += err;
- head.a_text -= err;
- offset += err;
- }
- while (((int)loadpoint) & CLOFSET)
- *(loadpoint++) = 0;
- /* printf("data=0x%X, ",head.a_data); */
- while (head.a_data > 0) {
- read_size = head.a_data > NFS_READ_SIZE ?
- NFS_READ_SIZE : head.a_data;
- if ((err = nfs_read(ARP_ROOTSERVER, root_nfs_port,
- (char *)&kernel_handle, offset, read_size, loadpoint)) !=
- read_size) {
- if (err < 0) {
- /* printf("Unable to read data: "); */
- nfs_err(err);
- }
- goto bootmenu;
- }
- loadpoint += err;
- head.a_data -= err;
- offset += err;
- }
- /* printf("bss=0x%X, ",head.a_bss); */
- while(head.a_bss--) *(loadpoint++) = 0;
-
- /* printf("entry=0x%X.\n\r",head.a_entry); */
-
- /* Jump to kernel */
- bootinfo.bi_version = BOOTINFO_VERSION;
- bootinfo.bi_kernelname = kernel;
- bootinfo.bi_nfs_diskless = &nfsdiskless;
- kernelentry = (void *)(head.a_entry & 0x00FFFFFF);
- (*kernelentry)(0,NODEV,0,0,0,&bootinfo,0,0,0);
- /* printf("*** %s execute failure ***\n",kernel); */
- #endif /* NETBOOT32 */
- }
-
- /**************************************************************************
- POLLKBD - Check for Interrupt from keyboard
- **************************************************************************/
- void pollkbd()
- {
- if (iskey() && (getchar() == ESC)) longjmp(jmp_bootmenu,1);
- }
-
- /**************************************************************************
- DEFAULT_NETMASK - Set a default netmask for IP address
- **************************************************************************/
- void default_netmask()
- {
- int net = arptable[ARP_CLIENT].ipaddr >> 24;
- if (net <= 127)
- netmask = htonl(0xff000000);
- else if (net < 192)
- netmask = htonl(0xffff0000);
- else
- netmask = htonl(0xffffff00);
- }
- /**************************************************************************
- UDP_TRANSMIT - Send a UDP datagram
- **************************************************************************/
- int udp_transmit(destip, srcsock, destsock, len, buf)
- unsigned long destip;
- unsigned int srcsock, destsock;
- int len;
- char *buf;
- {
- struct iphdr *ip;
- struct udphdr *udp;
- struct arprequest arpreq;
- int arpentry, i;
- int retry = MAX_ARP_RETRIES;
-
- ip = (struct iphdr *)buf;
- udp = (struct udphdr *)(buf + sizeof(struct iphdr));
- ip->verhdrlen = 0x45;
- ip->service = 0;
- ip->len = htons(len);
- ip->ident = 0;
- ip->frags = 0;
- ip->ttl = 60;
- ip->protocol = IP_UDP;
- ip->chksum = 0;
- convert_ipaddr(ip->src, (char *)&arptable[ARP_CLIENT].ipaddr);
- convert_ipaddr(ip->dest, (char *)&destip);
- ip->chksum = ipchksum((unsigned short *)buf, sizeof(struct iphdr));
- udp->src = htons(srcsock);
- udp->dest = htons(destsock);
- udp->len = htons(len - sizeof(struct iphdr));
- udp->chksum = 0;
- if (destip == IP_BROADCAST) {
- eth_transmit(broadcast, IP, len, buf);
- } else {
- long h_netmask = ntohl(netmask);
- /* Check to see if we need gateway */
- if (((destip & h_netmask) !=
- (arptable[ARP_CLIENT].ipaddr & h_netmask)) &&
- arptable[ARP_GATEWAY].ipaddr)
- destip = arptable[ARP_GATEWAY].ipaddr;
- for(arpentry = 0; arpentry<MAX_ARP; arpentry++)
- if (arptable[arpentry].ipaddr == destip) break;
- if (arpentry == MAX_ARP) {
- printf("\r\n%I is not in my arp table!\r\n", destip);
- return(0);
- }
- for (i = 0; i<ETHER_ADDR_SIZE; i++)
- if (arptable[arpentry].node[i]) break;
- if (i == ETHER_ADDR_SIZE) { /* Need to do arp request */
- arpreq.hwtype = htons(1);
- arpreq.protocol = htons(IP);
- arpreq.hwlen = ETHER_ADDR_SIZE;
- arpreq.protolen = 4;
- arpreq.opcode = htons(ARP_REQUEST);
- bcopy(arptable[ARP_CLIENT].node, arpreq.shwaddr,
- ETHER_ADDR_SIZE);
- convert_ipaddr(arpreq.sipaddr,
- (char *)&arptable[ARP_CLIENT].ipaddr);
- bzero(arpreq.thwaddr, ETHER_ADDR_SIZE);
- convert_ipaddr(arpreq.tipaddr, (char *)&destip);
- while (retry--) {
- eth_transmit(broadcast, ARP, sizeof(arpreq),
- (char *)&arpreq);
- if (await_reply(AWAIT_ARP, arpentry,
- arpreq.tipaddr)) goto xmit;
- }
- return(0);
- }
- xmit: eth_transmit(arptable[arpentry].node, IP, len, buf);
- }
- return(1);
- }
-
- /**************************************************************************
- TFTP - Try to load configuation file
- **************************************************************************/
- int tftp(name)
- char *name;
- {
- int retry = MAX_TFTP_RETRIES;
- static unsigned short isocket = 2000;
- unsigned short osocket;
- unsigned short len, block = 1, prevblock = 0;
- struct tftp_t *tr;
- struct tftp_t tp;
-
- tp.opcode = htons(TFTP_RRQ);
- len = (sprintf((char *)tp.u.rrq, "%s%coctet", name, 0)
- - ((char *)&tp)) + 1;
- if (!udp_transmit(arptable[ARP_SERVER].ipaddr, ++isocket, TFTP,
- len, (char *)&tp))
- return (0);
- for (;;)
- {
- if (!await_reply(AWAIT_TFTP, isocket, NULL))
- {
- if (prevblock == 0 && retry-- > 0)
- { /* maybe initial request was lost */
- if (!udp_transmit(arptable[ARP_SERVER].ipaddr,
- ++isocket, TFTP, len, (char *)&tp))
- return (0);
- continue;
- }
- break; /* timeout on other blocks */
- }
- tr = (struct tftp_t *)&packet[ETHER_HDR_SIZE];
- if (tr->opcode == ntohs(TFTP_ERROR))
- {
- printf("TFTP error %d (%s)\r\n",
- ntohs(tr->u.err.errcode),
- tr->u.err.errmsg);
- break;
- }
- if (tr->opcode != ntohs(TFTP_DATA))
- break;
- tp.opcode = htons(TFTP_ACK);
- block = ntohs(tp.u.ack.block = tr->u.data.block);
- osocket = ntohs(tr->udp.src);
- len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 4;
- if (len > TFTP_MAX_PACKET) /* shouldn't happen */
- continue; /* ignore it */
- udp_transmit(arptable[ARP_SERVER].ipaddr, isocket,
- osocket, TFTP_MIN_PACKET, (char *)&tp); /* ack */
- if (block <= prevblock) /* retransmission */
- continue; /* don't process */
- prevblock = block;
- if (block == 1)
- {
- if (len == TFTP_MAX_PACKET &&
- (((unsigned short *)tr->u.data.download)[255] == 0xAA55 ||
- *((unsigned long *)tr->u.data.download) == 0x1B031336l))
- printf("Tagged file format");
- else
- {
- bcopy(tr->u.data.download, config_buffer, len);
- config_buffer[len] = 0;
- return (1);
- }
- }
- if (!linux_tftp(block, tr->u.data.download, len))
- break;
- if (len < TFTP_MAX_PACKET) /* End of data */
- return (1);
- }
- return (0);
- }
-
- /**************************************************************************
- BOOTP - Get my IP address and load information
- **************************************************************************/
- int bootp()
- {
- int retry = MAX_BOOTP_RETRIES;
- struct bootp_t bp;
- unsigned long starttime;
- bzero(&bp, sizeof(struct bootp_t));
- bp.bp_op = BOOTP_REQUEST;
- bp.bp_htype = 1;
- bp.bp_hlen = ETHER_ADDR_SIZE;
- bp.bp_xid = starttime = currticks();
- bcopy(arptable[ARP_CLIENT].node, bp.bp_hwaddr, ETHER_ADDR_SIZE);
- while(retry--) {
- udp_transmit(IP_BROADCAST, 0, BOOTP_SERVER,
- sizeof(struct bootp_t), (char *)&bp);
- if (await_reply(AWAIT_BOOTP, 0, NULL)) {
- bcopy(&packet[ETHER_HDR_SIZE],(char *)&bootp_reply,sizeof(bootp_reply));
- return(1); }
- bp.bp_secs = htons((currticks()-starttime)/20);
- }
- return(0);
- }
-
-
- /**************************************************************************
- AWAIT_REPLY - Wait until we get a response for our request
- **************************************************************************/
- int await_reply(type, ival, ptr)
- int type, ival;
- char *ptr;
- {
- unsigned long time;
- struct iphdr *ip;
- struct udphdr *udp;
- struct arprequest *arpreply;
- struct bootp_t *bootpreply;
- struct rpc_t *rpc;
-
- int protohdrlen = ETHER_HDR_SIZE + sizeof(struct iphdr) +
- sizeof(struct udphdr);
- time = currticks() + TIMEOUT;
- while(time > currticks()) {
- pollkbd();
- if (eth_poll()) { /* We have something! */
- /* Check for ARP - No IP hdr */
- if ((type == AWAIT_ARP) &&
- (packetlen >= ETHER_HDR_SIZE +
- sizeof(struct arprequest)) &&
- (((packet[12] << 8) | packet[13]) == ARP)) {
- arpreply = (struct arprequest *)
- &packet[ETHER_HDR_SIZE];
- if ((arpreply->opcode == ntohs(ARP_REPLY)) &&
- bcompare(arpreply->sipaddr, ptr, 4)) {
- bcopy(arpreply->shwaddr,
- arptable[ival].node,
- ETHER_ADDR_SIZE);
- return(1);
- }
- continue;
- }
-
- /* Anything else has IP header */
- if ((packetlen < protohdrlen) ||
- (((packet[12] << 8) | packet[13]) != IP)) continue;
- ip = (struct iphdr *)&packet[ETHER_HDR_SIZE];
- if ((ip->verhdrlen != 0x45) ||
- ipchksum((unsigned short *)ip, sizeof(struct iphdr)) ||
- (ip->protocol != IP_UDP)) continue;
- udp = (struct udphdr *)&packet[ETHER_HDR_SIZE +
- sizeof(struct iphdr)];
-
- /* BOOTP ? */
- bootpreply = (struct bootp_t *)&packet[ETHER_HDR_SIZE];
- if ((type == AWAIT_BOOTP) &&
- (packetlen >= (ETHER_HDR_SIZE +
- sizeof(struct bootp_t))) &&
- (ntohs(udp->dest) == BOOTP_CLIENT) &&
- (bootpreply->bp_op == BOOTP_REPLY)) {
- convert_ipaddr((char *)&arptable[ARP_CLIENT].ipaddr,
- bootpreply->bp_yiaddr);
- default_netmask();
- convert_ipaddr((char *)&arptable[ARP_SERVER].ipaddr,
- bootpreply->bp_siaddr);
- bzero(arptable[ARP_SERVER].node,
- ETHER_ADDR_SIZE); /* Kill arp */
- convert_ipaddr((char *)&arptable[ARP_GATEWAY].ipaddr,
- bootpreply->bp_giaddr);
- bzero(arptable[ARP_GATEWAY].node,
- ETHER_ADDR_SIZE); /* Kill arp */
- if (bootpreply->bp_file[0]) {
- bcopy(bootpreply->bp_file,
- kernel_buf, 128);
- kernel = kernel_buf;
- }
- decode_rfc1048(bootpreply->bp_vend);
- return(1);
- }
-
- /* TFTP ? */
- if ((type == AWAIT_TFTP) &&
- (ntohs(udp->dest) == ival)) return(1);
-
- /* RPC */
- rpc = (struct rpc_t *)&packet[ETHER_HDR_SIZE];
- if ((type == AWAIT_RPC) &&
- (ntohs(udp->dest) == RPC_SOCKET) &&
- (ntohl(rpc->u.reply.id) == ival) &&
- (ntohl(rpc->u.reply.type) == MSG_REPLY)) {
- #ifdef NETBOOT32
- rpc_id++;
- #endif /* NETBOOT32 */
- return(1);
- }
- }
- }
- return(0);
- }
-
- /**************************************************************************
- DECODE_RFC1048 - Decodes RFC1048 header
- **************************************************************************/
- void decode_rfc1048(p)
- unsigned char *p;
- {
- static char rfc1048_cookie[4] = RFC1048_COOKIE;
- unsigned char *end = p + BOOTP_VENDOR_LEN,*q;
- if (bcompare(p, rfc1048_cookie, 4)) { /* RFC 1048 header */
- p += 4;
- while(p < end) {
- unsigned char c = *p;
- if (c == RFC1048_PAD) {p++; continue;}
- else if (c == RFC1048_END) {p = end; continue; }
- else if (c == RFC1048_NETMASK) {bcopy(p+2,&netmask,4); }
- else if (c == RFC1048_HOSTNAME) {
- bcopy(p+2,&nfsdiskless.my_hostnam,TAG_LEN(p));
- hostnamelen = (TAG_LEN(p)+3)&~3; }
- else {
- printf("Unknown RFC1048-tag ");
- for(q=p;q<p+2+TAG_LEN(p);q++)
- printf("%x ",*q);
- printf("\n\r"); }
- p += TAG_LEN(p) + 2;
- }
- }
- }
-
- /**************************************************************************
- IPCHKSUM - Checksum IP Header
- **************************************************************************/
- unsigned short ipchksum(ip, len)
- unsigned short *ip;
- int len;
- {
- unsigned long sum = 0;
- len >>= 1;
- while (len--) {
- sum += *(ip++);
- if (sum > 0xFFFF)
- sum -= 0xFFFF;
- }
- return((~sum) & 0x0000FFFF);
- }
-
-
- /**************************************************************************
- CONVERT_IPADDR - Convert IP address from net to machine order
- **************************************************************************/
- void convert_ipaddr(d, s)
- char *d,*s;
- {
- *(d+3) = *s;
- *(d+2) = *(s+1);
- *(d+1) = *(s+2);
- *d = *(s+3);
- }
-